(function() {
  'use strict'

  var global = tinymce.util.Tools.resolve('tinymce.PluginManager')
  var DOMUtils = tinymce.util.Tools.resolve('tinymce.dom.DOMUtils')
  var $ = tinymce.util.Tools.resolve('tinymce.dom.DomQuery')

  var popupTpl = `<div id="J_cfyun_atwho" class="cfyun-atwho" style="position:absolute;z-index: 1999;padding:0px;min-width:150px;max-width:180px;min-height:18px;border:1px solid #eee;background:#fff">
        <style>
            .cfyun-atwho-search{margin: 10px;}
            .cfyun-atwho-tip, .cfyun-atwho-tips{text-align: center;padding:5px 10px;color: #07f;}
            .cfyun-atwho-tips{color: #636b6f;}
            .cfyun-atwho-list{max-height: 300px;overflow: hidden;border-top: 1px solid #eee;}
            .cfyun-atwho-list ul{height: 100%;overflow-y: auto;}
            .cfyun-atwho-list ul::-webkit-scrollbar {width: 6px;display: none}
            .cfyun-atwho-list ul:hover::-webkit-scrollbar {display: block;}
            .cfyun-atwho-list ul::-webkit-scrollbar-thumb {border-radius: 3px;background: #ccd0d7}
            .cfyun-atwho-list-item{padding: 3px 10px;border-bottom: 1px solid #f8f8f8;user-select: none;-webkit-user-select: none;overflow: hidden;display: -webkit-box;-webkit-box-orient: vertical;-webkit-line-clamp: 1;}
            .cfyun-atwho-list-item.hover,.cfyun-atwho-list-item:hover{background-color: #E8F3FC;}
            .cfyun-atwho-list-item:last-child{border: 0;}
            .cfyun-atwho-list {
              max-height: 150px;
              overflow: auto;
            }
        </style>
        <div class="cfyun-atwho-wrap">
<!--            <div class="cfyun-atwho-tip">想用@提到谁？</div>-->
            <div class="cfyun-atwho-list"></div>
        </div>
    </div>`

  class AtWho {
    constructor(editor) {

      if (!editor.getParam('cfyun_atwho', !1, 'boolean')) {
        return
      }

      this.runtime = {
        at: editor.getParam('atwho_at', '@', 'string'),
        lindex: -1,
        cache: [],
        gspan: null,
        popup: null,
        enter: !1,
        isOpen: !1,
        imMode: !1,
        replaceAt: !1,
        queryTimer: null,
        errorTimer: null
      }

      this.editor = editor
      this.win = editor.getWin()
        	this.doc = editor.getDoc()
      // 最多艾特多少个用户
      this.maxNum = editor.getParam('atwho_max_num', 10, 'number')
      // 在不输入的情况查询好友列表
      this.queryAll = editor.getParam('atwho_query_all', !1, 'boolean')
      // 名字最多长度
      this.maxName = editor.getParam('atwho_max_name', 16, 'number')
      // 查询延时时间
      this.queryDelay = editor.getParam('atwho_query_delay', 200, 'number')
      // 查询回调, 需要实现ajax获取数据返回给本接口
      this.queryCallback = editor.getParam('atwho_query_callback', null, 'function')
      // 已选数据列表回调
      this.dataCallback = editor.getParam('atwho_data_callback', null, 'function')

      var _this = this

      this.event()

      return this
    }
    /**
         * 监听编辑器输入
         */
    event() {
      var _this = this

      this.editor.on('click', function(e) {
        if (_this.runtime.isOpen === true) {
          return !1
        }

        var node = _this.editor.selection.getNode()

        if (
          !$(node).hasClass('atwho') ||
                    !node.lastChild.nodeValue ||
                    (node.lastChild.nodeValue.split(_this.runtime.at)).length <= 1
        ) {
          return !1
        }

        var span = node

        $(node).parents().find('span.atwho').removeClass('atwho-wait')

        // 还原
        if (node.tagName === 'SPAN' && node.className.match('atwho')) {
          span = $('<span class="atwho">@</span>')
          $(node).replaceWith(span)
          span = span[0]
        } else {
          _this.runtime.replaceAt = !0
        }
        _this.runtime.replaceAt = !0

        $(span).addClass('atwho-wait')

        /*
                if(node.lastChild.nodeValue != _this.runtime.at) {
                    return !1;
                }*/

        var x = span.getBoundingClientRect().left
        var y = span.getBoundingClientRect().top

        _this.show(x, y)
        _this.getDataForCache()
        return !1
      })

      this.editor.on('keydown', function(e) {
        if (_this.runtime.queryTimer) {
          // clearTimeout(_this.runtime.queryTimer);
        }
        var keyCode = e.which || e.keyCode
        _this.runtime.imMode = e.shiftKey && (e.key == 'Process' || keyCode == 229 || keyCode == 197)

        if (_this.win.getSelection) {
          var sel = _this.win.getSelection()
          var rng = sel.getRangeAt(0)
        } else {
          var sel = _this.doc.selection
          var rng = sel.createRange()
        }

        if (e.shiftKey && e.key == '@') {
          if (_this.isCreateAt()) {
            return !1
          }

          _this.createAt()
          e.preventDefault()
          // } else if (_this.runtime.enter && e.key == 'Enter') {
        } else if (_this.runtime.enter && (e.key == 'Tab' || e.key == 'End')) { // 没办法这里只能用End插入, 因为tinymce的Enter被强制绑定的事件无法取消
          // } else if (_this.runtime.enter && (e.altKey == !0 && e.key == 'z')) {
          _this.replaceUser()
          e.preventDefault()
          e.isDefaultPrevented()
        } else if (/* e.code == 'Space' || */e.key == 'Enter') {
          e.preventDefault()
          e.isDefaultPrevented()
          _this.replaceUser()
          _this.hide()
          _this.reset()
        } else if (e.key == 'Backspace') {
          if (rng.startContainer.parentElement) {
					    var node = rng.startContainer.parentElement
            if (node && node.className.match('atwho') || node.className.match('atwho atwho-wait')) {
              var name = ''
              if (node.innerHTML) {
                name = node.innerHTML.substr(1)
              }
              // 剩下一个字符再删除
              if (name.length < 1 || node.tagName === 'A') {
                node.parentElement.removeChild(node)
                sel.removeAllRanges()
                sel.addRange(rng)
                _this.callbackData()
                // e.preventDefault();
                return !1
              }
            }
          } else {
            _this.hide()
          }
        } else if (_this.runtime.isOpen && e.key == 'ArrowUp') {
          _this.directionKey(-1)
          e.preventDefault()
        } else if (_this.runtime.isOpen && e.key == 'ArrowDown') {
          _this.directionKey(1)
          e.preventDefault()
        }
      })

      this.editor.on('keyup', function(e) {
        if (_this.win.getSelection) {
          var sel = _this.win.getSelection()
          var rng = sel.getRangeAt(0)
        } else {
          var sel = _this.doc.selection
          var rng = sel.createRange()
        }

        // 非英文输入模式
        if (_this.runtime.imMode) {
          if (!_this.isCreateAt()) {
            var node = rng.startContainer

            if (node && node.nodeValue != null) {
              var len = node.length
              var str = node.nodeValue.substr(len - 1, 1)
              if (str == _this.runtime.at) {
                rng.setStart(node, len - 1)
                rng.setEnd(node, len)
                rng.deleteContents()
                _this.createAt()
              }
            }
          }
        }

        if (!_this.runtime.gspan) {
          return !1
        }

        if (_this.runtime.errorTimer) {
          clearTimeout(_this.runtime.errorTimer)
        }

        if (_this.runtime.isOpen && _this.runtime.gspan != null) {
          if (e.key == 'ArrowUp' || e.key == 'ArrowLeft' || e.key == 'ArrowRight' || e.key == 'ArrowDown' || e.key == 'Shift') {
            return !1
          }

          var _gval = ''
          if (_this.runtime.gspan.innerHTML) {
            _gval = _this.runtime.gspan.innerHTML.substr(1)
          }

          // 超出截取
          if (_gval && _gval.length >= _this.maxName) {
            _gval = _gval.slice(0, _this.maxName)
            return !1
          }

          if (e.key == 'Backspace') {
            if (_this.runtime.gval == '') {
              _this.reset()
              return !1
            }

            if ($('#J_cfyun_atwho').length) {
              $('#J_cfyun_atwho').css('display', 'block')
            }
          }

          // 直接查询所有
          if (_gval === '' && _this.queryAll === !0) {
            _gval = 'all'
            _this.runtime.gval = ''
          }

				    if (_this.runtime.isOpen && _gval != '') {
            if (_gval !== 'all') {
              _this.runtime.gval = _gval
            }

            _this.getDataForCache()

            // 延时查询
            _this.runtime.queryTimer = setTimeout(function() {
              _this.getData()
            }, _this.queryDelay)

          }
        }
        e.preventDefault()
      })

      this.editor.on('mousedown', function(e) {
        _this.hide()
      })
    }
    /**
         * 是否创建at节点
         */
    isCreateAt() {
      var node = this.editor.selection.getNode()
      if (this.maxNum != 0 && this.count() >= this.maxNum) {
        return !0
      }

      var isHas = $(node).hasClass('atwho')
      /*
            if(isHas && ($(node).html().split(this.runtime.at)).length > 2) {
                this.runtime.gspan = null;
                this.hide();
                $(node).replaceWith($(node).html());
            }
            */
      return isHas
    }
    /**
         * 创建at节点
         */
    createAt() {
      if (this.win.getSelection()) {
        var sel = this.win.getSelection()
        var rng = sel.getRangeAt(0)
      } else {
        var sel = this.doc.selection
        var rng = sel.createRange()
      }

      var id = 'J_atwho_tmp' + (+new Date())
      this.addAt('<span class="atwho atwho-wait" id="' + id + '">@</span>')
      var span = this.doc.getElementById(id)

      this.runtime.gspan = span

      var x = span.getBoundingClientRect().left
      var y = span.getBoundingClientRect().bottom

      var ospan = span.firstChild

      rng.setStart(ospan, 1)
      rng.setEnd(ospan, 1)
      // sel.removeAllRanges()
      // sel.addRange(rng)

      this.show(x, y)
    }
    /**
         * 显示at用户的窗口
         */
    show(x, y) {
      var st = document.documentElement.scrollTop + document.body.scrollTop
      var content = this.editor.iframeElement
      var x0 = content.getBoundingClientRect().left + 11
      var y0 = content.getBoundingClientRect().bottom + 20 + st

      var popup
      if (document.querySelectorAll('#J_cfyun_atwho').length) {
        popup = document.querySelectorAll('#J_cfyun_atwho')[0]
        popup.style.display = 'block'
      } else {
        popup = $(popupTpl)[0]
        $(document.body).append(popup)
      }

      popup.style.left = x + x0 + 'px'
      popup.style.bottom = y + 110 + 'px'
      this.runtime.isOpen = !0
      this.runtime.popup = popup
    }
    /**
         * 隐藏艾特用户窗口
         */
    hide() {
      if (this.runtime.popup) {
        this.runtime.isOpen = !1
        this.runtime.popup.style.display = 'none'
      }
    }
    /**
         * 插入at用户
         */
    addUser(user) {
      var node = this.editor.selection.getNode()

      // if (node.tagName == 'P') {
      //   node = $(node).find('span.atwho.atwho-wait')[0]
      //   // this.runtime.replaceAt = !0;
      // }
      if (!node.className.match('atwho-wait')) {
        node = $(node).find('span.atwho.atwho-wait')[0]
      }

      // if (this.runtime.replaceAt) {
      //   var _node = node.lastChild
      //   /*
      //           if(_node && _node.nodeValue != null && _node.nodeValue.indexOf(this.runtime.at) != -1) {
      //               this.removeUser(_node.nodeValue.replace(this.runtime.at, ''));
      //           }*/
      // }

      $(node).replaceWith(`<span class="atwho teacher-zone-disabled-edit editor-notice color-primary" contenteditable="false" data-noticeId="${user.uid}" data-uid="${user.uid}">@${user.name}</span>&nbsp;`)

      this.hide()
      this.editor.focus()

      // if (this.runtime.replaceAt) {
      //   this.runtime.replaceAt = !1
      // }

      this.callbackData()
    }
    replaceUser() {
      if (this.runtime.lindex == -1 || !this.usableUser) {
        return !1
      }

      this.addUser(this.usableUser)
    }
    callbackData() {
      let _this = this

      let list = []
      let atList = $(this.editor.getBody()).find('.atwho')

      if (atList.length) {
        $.each(atList, function(i, value) {
          var $this = $(value)
          list.push({
            uid: $this.attr('data-uid'),
            name: $this.text().replace(_this.runtime.at, ''),
            url: $this.attr('href')
          })
        })
      }

      // 设置回调方法后, 则不设置监听事件回调方式
      if (typeof this.dataCallback == 'function') {
        this.dataCallback(list)
        return !1
      }

      this.editor.fire('atwho', { list: list })
    }
    count() {
      return $(this.editor.getBody()).find('.atwho').length || 0
    }
    /**
         * 填充好友列表
         */
    fillUserTpl(list) {
      var li = '', node = this.editor.selection.getNode()
      if (node.innerHTML && node.className == 'atwho atwho-wait') {
        var keyword = node.innerHTML
        keyword = keyword.substr(1, keyword.length)
      }

      if (keyword) {
        list = this.search(list, 'username', keyword)
      }

      for (var i = 0; i < list.length; i++) {
        var name = list[i].username
        if (keyword && name && name.indexOf(keyword) != -1) {
          name = name.replace(keyword, `<strong style="color: #07f">${keyword}</strong>`)
        }

        li += `<li class="cfyun-atwho-list-item" data-url="${list[i].url}" data-uid="${list[i].uid}">${name}</li>`
      }
      $(this.runtime.popup).find('.cfyun-atwho-list').html(`<ul>${li}</ul>`)
      this.addUserEvent()
    }
    /**
         * 根据输入获取好友
         */
    getData() {
      if ((!this.runtime.gval || this.runtime.gval == '') && this.queryAll !== !0) {
        return !1
      }

      this.showTips(!0, '加载中...')

      var _this = this
      // 使用回调获取好友列表
      this.queryCallback(this.runtime.gval, list => {
        if (!list || !list.length) {
          // 查找不到用户
          var node = _this.editor.selection.getNode()
          if (!node) {
            return !1
          }
          // 未包含.时
          if (node.innerHTML && node.innerHTML.indexOf('.') === -1) {
            _this.showTips(!0, '没有您要找的用户')
            _this.runtime.errorTimer = setTimeout(() => {
              _this.hide()
            }, 1500)
          } else {
            // 输入包含.可能是要输入邮箱, 则恢复@符
            if (node.className == 'atwho' || node.className == 'atwho atwho-wait') {
              _this.hide()
              _this.runtime.gspan = null
              $(node).replaceWith($(node).html())
            }
          }
          return !1
        }
        _this.showTips(!1)
        _this.fillUserTpl(list)
        _this.runtime.cache.push({
          key: _this.runtime.gval,
          items: list
        })
      })
    }
    getDataForCache() {
      if (this.runtime.cache.length >= 1) {
        for (var i = 0, len = this.runtime.cache.length;i < len;i++) {
          if (this.runtime.gval == this.runtime.cache[i].key) {
            this.fillUserTpl(this.runtime.cache[i].items)
            return false
          }
        }
      }
    }
    showTips(isShow, msg) {
      var tips = $(this.runtime.popup).find('.cfyun-atwho-list')

      if (msg) {
        tips.html(`<div class="cfyun-atwho-tips">${msg}</div>`)
        return !1
      }
      tips.find('.cfyun-atwho-tips').remove()
    }
    directionKey(i) {
      if (!this.runtime.popup) {
        return !1
      }

      var lis = $(this.runtime.popup).find('.cfyun-atwho-list li')

      if (!lis.length) {
        return !1
      }

      var l = lis.length - 1

      // 方向键控制
      if (i == -1) {
        this.runtime.lindex = this.runtime.lindex <= -1 ? l : this.runtime.lindex - 1
      } else {
        this.runtime.lindex = this.runtime.lindex >= l ? -1 : this.runtime.lindex + 1
      }

      lis.removeClass('hover')

      if (this.runtime.lindex != -1) {
        this.hover(this.runtime.lindex)
      } else {
        this.usableUser = {}
        this.runtime.enter = !1
      }
    }
    hover(index) {
      if (!this.runtime.popup) {
        return !1
      }

      this.runtime.lindex = index
      this.runtime.enter = !0

      var current = $(this.runtime.popup).find('.cfyun-atwho-list li').eq(index)

      current.addClass('hover')

      this.usableUser = {
        name: current.html(),
        uid: current.attr('data-uid'),
        url: current.attr('data-url')
      }
    }
    /**
         * 监听插入at用户事件
         */
    addUserEvent() {
      var _this = this

      if (!this.runtime.popup) {
        return !1
      }

      $(this.runtime.popup).find('.cfyun-atwho-list li').off('click').on('click', function(e) {
        var $this = $(this)
        var name = $this.text().trim()
        var uid = $this.attr('data-uid')
        var url = $this.attr('data-url')

        _this.addUser({
          uid: uid,
          name: name,
          url: url
        })
      })
    }
    /**
         * 插入at节点
         */
    addAt(html) {
      if (!this.doc.selection) {
        var sel = this.win.getSelection()
        var rng = sel.getRangeAt(0)
        var fragment = rng.createContextualFragment(html)
        rng.insertNode(fragment)
      } else {
        var range = this.doc.selection.createRng()
        range.pasteHTML(html)
      }
    }
    search(array, type, value) {
      if (!$.isArray(array)) {
        return !1
      }

      var arr = []
      arr = array.filter(function(a) {
        return a[type].toString().indexOf(value) != -1
      })

      return arr
    }
    /**
         * 重置
         */
    reset() {
      this.hide()
      $(this.runtime.popup).remove()
      this.runtime.lindex = -1
      this.runtime.gspan = null
      this.runtime.gval = null
      this.runtime.popup = null
      this.runtime.enter = !1
      this.runtime.isOpen = !1
      this.runtime.imMode = !1
      this.runtime.replaceAt = !1
      this.runtime.queryTimer = null
      this.runtime.errorTimer = null
    }
  }

  function Plugin() {
    global.add('atwho', function(editor) {
      editor.on('init', function(e) {
        new AtWho(editor)
      })
    })
  }

  Plugin()

}())
